package com.tianji.learning.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.api.cache.CategoryCache;
import com.tianji.api.client.course.CatalogueClient;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.client.search.SearchClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.course.CataSimpleInfoDTO;
import com.tianji.api.dto.course.CourseSimpleInfoDTO;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.BooleanUtils;
import com.tianji.common.utils.ObjectUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.QuestionFormDTO;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.query.QuestionAdminPageQuery;
import com.tianji.learning.domain.query.QuestionPageQuery;
import com.tianji.learning.domain.vo.QuestionAdminVO;
import com.tianji.learning.domain.vo.QuestionVO;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.service.IInteractionQuestionService;
import com.tianji.learning.service.IInteractionReplyService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 互动提问的问题表 服务实现类
 * </p>
 *
 * @author 东哥
 * @since 2024-08-25
 */
@Service
@RequiredArgsConstructor
public class InteractionQuestionServiceImpl extends ServiceImpl<InteractionQuestionMapper, InteractionQuestion> implements IInteractionQuestionService {
    private final IInteractionReplyService replyService;
    private final UserClient userClient;
    private final SearchClient searchClient;
    private final CourseClient courseClient;
    private final CatalogueClient catalogueClient;
    private final CategoryCache categoryCache;

    /**
     * 1、用户端-新增互动问题（Day5 - 随堂1）
     *
     * @param questionFormDTO 参数dto
     */
    @Override
    public void saveQuestion(QuestionFormDTO questionFormDTO) {
        // 1、数据拷贝
        InteractionQuestion question = BeanUtils.copyBean(questionFormDTO, InteractionQuestion.class);

        // 2、补充用户ID
        question.setUserId(UserContext.getUser());

        // 3、新增数据
        this.save(question);
    }

    /**
     * 2、用户端-分页查询互动问题（Day5 - 随堂2）
     *
     * @param query
     * @return
     */
    @Override
    public PageDTO<QuestionVO> pageQuery(QuestionPageQuery query) {
        // 1、参数校验：课程ID和小节ID不能同时为空
        Long courseId = query.getCourseId();
        Long sectionId = query.getSectionId();
        if (ObjectUtils.isEmpty(courseId) && ObjectUtils.isEmpty(sectionId)) {
            throw new BadRequestException("课程ID和小节ID不能同时为空！");
        }

        // 2、分页查询
        // select * from interaction_question where course_id = ? and section_id = ? and user_id = ? and hidden = 0
        // order by create_time desc limit ?,?
        Page<InteractionQuestion> pageResult = this.lambdaQuery()
                .select(InteractionQuestion.class, column -> !column.getColumn().equals("description")) // select 断言，只查询description以外的字段
                .eq(ObjectUtils.isNotEmpty(courseId), InteractionQuestion::getCourseId, courseId)
                .eq(ObjectUtils.isNotEmpty(sectionId), InteractionQuestion::getSectionId, sectionId)
                .eq(BooleanUtils.isTrue(query.getOnlyMine()), InteractionQuestion::getUserId, UserContext.getUser())
                .eq(InteractionQuestion::getHidden, false)
                .page(query.toMpPageDefaultSortByCreateTimeDesc());
        List<InteractionQuestion> records = pageResult.getRecords();
        if (ObjectUtils.isEmpty(records)) {
            return PageDTO.empty(pageResult);
        }

        // 3、补充信息查询，查询提问者信息（非匿名的）、查询最近一次回答信息
        // 3.1、收集提问者ID集合，最近一次回答ID集合
        Set<Long> userIds = new HashSet<>();
        Set<Long> lastAnswerIds = new HashSet<>(records.size());
        for (InteractionQuestion record : records) {
            if (!record.getAnonymity()) {
                userIds.add(record.getUserId());
            }
            lastAnswerIds.add(record.getLatestAnswerId());
        }

        // 3.2、根据最近一次回答ID集合进行查询 -> 转成Map（最近一次回答ID ： 最近一次回答信息对象）
        Map<Long, InteractionReply> replyMap = new HashMap<>(lastAnswerIds.size());
        List<InteractionReply> lastReplyList = replyService.listByIds(lastAnswerIds);
        if (ObjectUtils.isNotEmpty(lastReplyList)) {
            for (InteractionReply reply : lastReplyList) {
                replyMap.put(reply.getId(), reply);
                if (!reply.getAnonymity()) {
                    userIds.add(reply.getUserId());
                }
            }
        }

        // 3.3、 根据提问者ID集合远程调用用户服务，查询用户信息 -> 转成Map（用户ID：用户信息对象）
        Map<Long, UserDTO> userInfoMap = new HashMap<>(userIds.size());
        if (ObjectUtils.isNotEmpty(userIds)) {
            List<UserDTO> userInfoList = userClient.queryUserByIds(userIds);
            if (ObjectUtils.isNotEmpty(userInfoList)) {
                userInfoMap = userInfoList.stream().collect(Collectors.toMap(UserDTO::getId, Function.identity()));
            }
        }

        // 4、循环遍历分页数据，封装VO集合
        List<QuestionVO> voList = new ArrayList<>(records.size());
        for (InteractionQuestion record : records) {
            // 4.1、将po转为vo
            QuestionVO vo = BeanUtils.copyBean(record, QuestionVO.class);

            // 4.2、补充提问者信息（提问者昵称、头像）
            if (!record.getAnonymity()) {
                UserDTO userInfo = userInfoMap.get(record.getUserId());
                if (ObjectUtils.isNotEmpty(userInfo)) {
                    vo.setUserName(userInfo.getName());
                    vo.setUserIcon(userInfo.getIcon());
                }
            }

            // 4.3、补充最近一次回答信息（最近一次回答者昵称、最近一次回答内容）
            InteractionReply lastReply = replyMap.get(record.getLatestAnswerId());
            if (ObjectUtils.isNotEmpty(lastReply)) {
                vo.setLatestReplyContent(lastReply.getContent());
                if (!lastReply.getAnonymity()) {
                    UserDTO userInfo = userInfoMap.get(lastReply.getUserId());
                    if (ObjectUtils.isNotEmpty(userInfo)) {
                        vo.setLatestReplyUser(userInfo.getName());
                    }
                }
            }

            // 4.4、将vo添加至volist
            voList.add(vo);
        }

        // 5、组装PageDTO并返回
        return PageDTO.of(pageResult, voList);
    }

    /**
     * 3、用户端-根据ID查询互动问题（Day5 - 随堂3）
     *
     * @param id 问题ID
     * @return
     */
    @Override
    public QuestionVO queryById(Long id) {
        // 1、根据ID查询问题
        InteractionQuestion question = this.getById(id);
        if (ObjectUtils.isEmpty(question) || question.getHidden()) {
            return null;
        }

        // 2、查询提问者信息
        UserDTO userInfo = null;
        if (!question.getAnonymity()) {
            userInfo = userClient.queryUserById(question.getUserId());
        }

        // 3、封装VO并返回
        QuestionVO vo = BeanUtils.copyBean(question, QuestionVO.class);
        if (ObjectUtils.isNotEmpty(userInfo)) {
            vo.setUserName(userInfo.getName());
            vo.setUserIcon(userInfo.getIcon());
        }
        return vo;
    }

    /**
     * 4、管理端-分页查询互动问题（Day5 - 随堂4）
     *
     * @param query
     * @return
     */
    @Override
    public PageDTO<QuestionAdminVO> adminPageQuery(QuestionAdminPageQuery query) {
        // 1、调用ES处理课程名称，得到课程ID集合
        List<Long> courseIds = null;
        if (ObjectUtils.isNotEmpty(query.getCourseName())) {
            courseIds = searchClient.queryCoursesIdByName(query.getCourseName());
            if (ObjectUtils.isEmpty(courseIds)) {
                return PageDTO.empty(0L, 0L);
            }
        }

        // 2、分页查询问题列表
        // select * from interaction_question where course_id in (1,2,3)
        // and status = ? and create_time >= ? and  create_time <= ? order by create_time desc limit ?,?
        Page<InteractionQuestion> pageResult = this.lambdaQuery()
                .in(ObjectUtils.isNotEmpty(courseIds), InteractionQuestion::getCourseId, courseIds)
                .eq(ObjectUtils.isNotEmpty(query.getStatus()), InteractionQuestion::getStatus, query.getStatus())
                .ge(ObjectUtils.isNotEmpty(query.getBeginTime()), InteractionQuestion::getCreateTime, query.getBeginTime())
                .le(ObjectUtils.isNotEmpty(query.getEndTime()), InteractionQuestion::getCreateTime, query.getEndTime())
                .page(query.toMpPageDefaultSortByCreateTimeDesc());
        List<InteractionQuestion> records = pageResult.getRecords();
        if (ObjectUtils.isEmpty(records)) {
            return PageDTO.empty(pageResult);
        }

        // 3、补充信息查询（章节数据、课程数据、用户数据）
        // 3.0、收集各种业务ID
        Set<Long> userIds = new HashSet<>(records.size());   //  用户ID 集合
        Set<Long> cIds = new HashSet<>(records.size());      //  课程ID 集合
        Set<Long> cataIds = new HashSet<>(records.size());   //  章节ID 集合
        records.forEach(r -> {
            userIds.add(r.getUserId());
            cIds.add(r.getCourseId());

            cataIds.add(r.getChapterId());
            cataIds.add(r.getSectionId());
        });

        // 3.1、根据用户ID集合查询用户数据
        Map<Long, String> userInfoMap = new HashMap<>(userIds.size());
        List<UserDTO> userInfoList = userClient.queryUserByIds(userIds);
        if (ObjectUtils.isNotEmpty(userInfoList)) {
            userInfoMap = userInfoList.stream().collect(Collectors.toMap(UserDTO::getId, UserDTO::getName));
        }

        // 3.2、根据课程ID集合查询课程数据
        Map<Long, CourseSimpleInfoDTO> courseInfoMap = new HashMap<>(cIds.size());
        List<CourseSimpleInfoDTO> courseInfoList = courseClient.getSimpleInfoList(cIds);
        if (ObjectUtils.isNotEmpty(courseInfoList)) {
            courseInfoMap = courseInfoList.stream().collect(Collectors.toMap(CourseSimpleInfoDTO::getId, Function.identity()));
        }

        // 3.3、根据章节ID集合查询章节数据
        Map<Long, String> cataInfoMap = new HashMap<>(cataIds.size());
        List<CataSimpleInfoDTO> cataInfoList = catalogueClient.batchQueryCatalogue(cataIds);
        if (ObjectUtils.isNotEmpty(cataInfoList)) {
            cataInfoMap = cataInfoList.stream().collect(Collectors.toMap(CataSimpleInfoDTO::getId, CataSimpleInfoDTO::getName));
        }

        // 4、循环列表，填充各种数据
        List<QuestionAdminVO> voList = new ArrayList<>(records.size());
        for (InteractionQuestion record : records) {
            // 4.1、属性拷贝，po -> vo
            QuestionAdminVO adminVO = BeanUtils.copyBean(record, QuestionAdminVO.class);

            // 4.2、填充用户昵称
            adminVO.setUserName(userInfoMap.getOrDefault(record.getUserId(), ""));

            // 4.3、填充课程名称 和 三级分类信息
            CourseSimpleInfoDTO courseInfo = courseInfoMap.get(record.getCourseId());
            if (ObjectUtils.isNotEmpty(courseInfo)) {
                adminVO.setCourseName(courseInfo.getName());
                // 已知： 三级分类ID集合  ——> 三级分类名称拼接字符串
                adminVO.setCategoryName(categoryCache.getCategoryNames(courseInfo.getCategoryIds()));
            }

            // 4.4、填充章节名称
            adminVO.setChapterName(cataInfoMap.getOrDefault(record.getChapterId(), ""));
            adminVO.setSectionName(cataInfoMap.getOrDefault(record.getSectionId(), ""));

            // 4.5、添加·vo至volist
            voList.add(adminVO);
        }


        // 5、封装并返回PageDTO
        return PageDTO.of(pageResult,voList);
    }

}
